#ifndef __ESP_WIFI_H__
#define __ESP_WIFI_H_

#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <linux/err.h>
#include <linux/cdev.h> 

#define ESP_OK 0
#define ESP_NO -1

#define ESP_IF_TYPE_SPI		2
#define ESP_PAYLOAD_HEADER		8

typedef enum {
	ESP_STA_IF,
	ESP_AP_IF,
	ESP_SERIAL_IF,
	ESP_HCI_IF,
	ESP_PRIV_IF,
	ESP_NULL,
} ESP_INTERFACE_TYPE;

#define ESP_MAX_INTERFACE		2

struct esp_adapter;

struct esp_if_ops {
	int (*init)(struct esp_adapter *adapter);
	struct sk_buff* (*read)(struct esp_adapter *adapter);
	int (*write)(struct esp_adapter *adapter, u8 *buf, u32 size);
	int (*deinit)(struct esp_adapter *adapter);
};

struct esp_adapter {
	u8				if_type;
	u32				capabilities;

	/* Possible types:
	 * 	struct esp_sdio_context */
	void				*if_context;

	struct esp_if_ops		*if_ops;

	/* Private for each interface */
	struct esp_private		*priv[ESP_MAX_INTERFACE];
	struct hci_dev 			*hcidev;

	struct workqueue_struct 	*if_rx_workqueue;
	struct work_struct		if_rx_work;

	/* Process TX work */
	struct workqueue_struct 	*tx_workqueue;
	struct work_struct		tx_work;

	/* TX queue */
	struct sk_buff_head 		tx_q;

	/* RX Queue */
	struct sk_buff_head 		rx_q;

	/* Counters */
	atomic_t			tx_pending;
	atomic_t			rx_pending;
};

struct esp_private {
	struct esp_adapter		*adapter;
	struct net_device		*ndev;
	struct net_device_stats 	stats;
	u8				link_state;
	u8				mac_address[6];
	u8 				if_type;
	u8			 	if_num;
};

struct esp_skb_cb {
	struct esp_private		*priv;
};

/* 协议处理 */
struct esp_payload_header {
	uint8_t 		 if_type:4;
	uint8_t 		 if_num:4;
	uint8_t			 reserved1;
	uint16_t                 len;
	uint16_t                 offset;
	uint8_t                  reserved2;
	union {
		uint8_t		 reserved3;
		uint8_t		 hci_pkt_type;		/* Packet type for HCI interface */
		uint8_t		 priv_pkt_type;		/* Packet type for priv interface */
	};
} __attribute__((packed));

typedef struct spi_dev{
	dev_t devid;
	int major;
	struct cdev cdev;
	struct device *device;
	struct class *class;
}spi_dev_t;

struct esp_spi_context {
	struct esp_adapter 	*adapter;
	struct spi_device 	*esp_spi_dev;
	struct sk_buff_head 	tx_q;
	struct sk_buff_head 	rx_q;
	struct workqueue_struct 	*spi_workqueue;
	struct work_struct		spi_work;
	spi_dev_t spi_dev;
};

int esp_init_interface_layer(struct esp_adapter *adapter);
struct sk_buff * esp_alloc_skb(u32 len);
int esp_add_card(struct esp_adapter *adapter);
void esp_process_new_packet_intr(struct esp_adapter *adapter);
int esp_remove_card(struct esp_adapter *adapter);
void esp_deinit_interface_layer(void);
void print_hex_dump_bytes(const char *prefix_str, int prefix_type,  
                           const void *buf, size_t len);
#endif